#include "controller/AdUrlHandler.h"

#include "ServerContext.h"

#include "DBPool.h"
#include "RedisConnetionPool.h"

#include <time.h>
#include <MD5.h>

#include "RapidJsonMacro.h"

AdUrlHandler::AdUrlHandler(const std::string& url):FastCgiHandler(url){

}

AdUrlHandler::~AdUrlHandler(){

}

void AdUrlHandler::doGet(const Fastcgipp::Http::Environment<char>& env,std::basic_ostream<char>& resp){
    resp << "Content-Type: application/json; charset=utf-8\r\n\r\n";
    std::string out;
    std::string user_agent;
    int agent_id;

    rapidjson::Document d;
    rapidjson::Value obj(rapidjson::kObjectType);

    rapidjson::Document::AllocatorType& allocator = d.GetAllocator();

    //获取请求参数
    auto param = env.gets;

    auto it = param.find("sign");

    if(it == param.end()) {
        RapidJsonObjAddMember(d,obj,"code",-1);
        RapidJsonObjAddMember(d,obj,"msg","参数不合法，请检查！");

        RapidJsonGetString(obj,out);

        resp<<out;

        return ;
    }

    //对sign计算md5
    std::string sign = it->second;
    MD5 md5;
    std::string sign_md5 = md5.getMd5(sign);

    Context* ctx = ServerContext::getInstance();
    CDBPool* dbpool = static_cast<CDBPool*>(ctx->getContext("dbpool_ad"));
    CacheConnectionPool* cache_pool = static_cast<CacheConnectionPool*>(ctx->getContext("cache_pool"));
    CacheConnection* cache_conn = cache_pool->getCacheConnection();
    if(cache_conn == NULL) {
        RapidJsonObjAddMember(d,obj,"code",-1);
        RapidJsonObjAddMember(d,obj,"msg","获取缓存连接失败！");

        RapidJsonGetString(obj,out);

        resp<<out;

        return ;
    }

    //从缓存中获取数据
    std::string cache_val;
    if(cache_conn->get(sign_md5.c_str(),cache_val)) {
        resp<<cache_val;
        cache_pool->putCacheConnection(cache_conn);

        return ;
    }

    char sql[128];
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select agent_id from tb_ad_user_inf where sign='%s' limit 1",sign_md5.c_str());

    CDBConn* conn = dbpool->GetDBConn();
    CResultSet* res = conn->ExecuteQuery(sql);

    if(res && res->GetResultCount()) {
        if(res->Next()) {
            agent_id = res->GetInt("agent_id");

            memset(sql,0,sizeof(sql));
            sprintf(sql,"select user_agent from tb_user_agent where id = %d",agent_id);

            CResultSet* res_agent = conn->ExecuteQuery(sql);
            if(res_agent) {
                if(res_agent->Next()) {
                    char* ret = res_agent->GetString("user_agent");
                    user_agent.assign(ret,ret + strlen(ret));
                    delete res_agent;
                }
            }

            delete res;
        }

    }else {
        //新请求的用户
        memset(sql,0,sizeof(sql));
        sprintf(sql,"select id,user_agent from tb_user_agent");

        CResultSet* res_agent = conn->ExecuteQuery(sql);
        if(res_agent) {
            res_agent->GetDataSeek(rand()% res_agent->GetResultCount());

            if(res_agent->Next()) {
                agent_id = res_agent->GetInt("id");
                char* ret = res_agent->GetString("user_agent");
                user_agent.assign(ret,ret + strlen(ret));
            }

            delete res_agent;
        }

        memset(sql,0,sizeof(sql));
        sprintf(sql,"insert into tb_ad_user_inf(sign,agent_id) values('%s',%d)",sign_md5.c_str(),agent_id);
        if(!conn->ExecuteUpdate(sql)) {
            obj.AddMember("msg","未知错误！",allocator);

            RapidJsonObjAddMember(d,obj,"code",-1);
            RapidJsonObjAddMember(d,obj,"msg","未知错误！");

            RapidJsonGetString(obj,out);

            resp<<out;

            dbpool->RelDBConn(conn);
            cache_pool->putCacheConnection(cache_conn);

            return ;
        }
    }

    //获取广告url
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select url from tb_ad_url where type=1 and validate=1");
    res = conn->ExecuteQuery(sql);
    if(res && res->Next()) {
        const char* url = res->GetString("url");

        rapidjson::Value data(rapidjson::kObjectType);
        RapidJsonObjAddStrMember(d,data,"url",url);
        RapidJsonObjAddStrMember(d,data,"user_agent",user_agent.c_str());

        RapidJsonObjAddMember(d,obj,"code",0);
        RapidJsonObjAddMember(d,obj,"msg","success");
        RapidJsonObjAddMember(d,obj,"data",data);

        RapidJsonGetString(obj,out);

        resp<<out;

        //设置缓存
        cache_conn->set(sign_md5.c_str(),out.c_str(),REDIS_12_HOURS);
    }

    delete res;

    dbpool->RelDBConn(conn);
    cache_pool->putCacheConnection(cache_conn);

    return ;
}

void AdUrlHandler::doPost(const Fastcgipp::Http::Environment<char>& env,std::basic_ostream<char>& resp){
    resp<< "Content-Type: application/json; charset=utf-8\r\n\r\n";

    resp<<"Hello,AdUrlHandler post!";
}
